package com.snow.useviewdemo.function2.radius;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

import com.luck.picture.lib.tools.ScreenUtils;
import com.snow.useviewdemo.R;


public class SpeedometerProgressView extends View {

    private static final String TAG = SpeedometerProgressView.class.getSimpleName();

    private Context mContext;
    //默认大小
    private int mDefaultSize;
    //是否开启抗锯齿
    private boolean antiAlias;

    private float mValue;
    private float mMaxValue;

    private float leftPointRadius = 20;

    //绘制圆弧
    private float mArcWidth;
    private float mStartAngle, mSweepAngle;
    private RectF mRectF;
    private RectF mProgressRectF;
    //当前进度，[0.0f,1.0f]
    private float mPercent;
    //动画时间
    private long mAnimTime;
    //属性动画
    private ValueAnimator mAnimator;

    //绘制背景圆弧
    private Paint mBgArcPaint;
    private Paint mBgGrayArcPaint;
    private Paint mProgressPaint;
    private Paint mProgressShadowPaint;
    private Paint mCirclePaint;
    private Paint mProgressBgPaint;
    private Paint mArcPaint;
    private int mBgArcColor;
    private float mBgArcWidth;

    //圆心坐标，半径
    private Point mCenterPoint;
    private float mRadius;

    private float mShadowSize = ScreenUtils.dip2px(getContext(), 20);

    private int mArcCenterX;
    // 内部虚线的外部半径
    private float mExternalDottedLineRadius;
    // 内部虚线的内部半径
    private float mInsideDottedLineRadius;

    // 线条数
    private int mDottedLineCount = 6;
    // 圆弧跟虚线之间的距离
    private int mLineDistance = 20;
    // 线条宽度
    private float mDottedLineWidth = 40;
    private Paint drawPaint;
    private ColorPickGradient mColorPickGradient;

    private float mBgGrayWidth = ScreenUtils.dip2px(getContext(), 15);
    private float mProgressWidth = ScreenUtils.dip2px(getContext(), 15);
    private float mProgressBgWidth = ScreenUtils.dip2px(getContext(), 30);

    public SpeedometerProgressView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        mContext = context;
        mDefaultSize = dipToPx(mContext, 150);
        mAnimator = new ValueAnimator();
        mRectF = new RectF();
        mProgressRectF = new RectF();
        mCenterPoint = new Point();
        initAttrs(attrs);
        initPaint();

        mColorPickGradient = new ColorPickGradient(context);

        setLayerType(LAYER_TYPE_SOFTWARE, null);
    }

    private void initAttrs(AttributeSet attrs) {
        TypedArray typedArray = mContext.obtainStyledAttributes(attrs, R.styleable.CircleProgressBar);

        antiAlias = typedArray.getBoolean(R.styleable.CircleProgressBar_antiAlias, true);

        mValue = typedArray.getFloat(R.styleable.CircleProgressBar_value, 0);
        mMaxValue = typedArray.getFloat(R.styleable.CircleProgressBar_maxValue, 500);

        mArcWidth = typedArray.getDimension(R.styleable.CircleProgressBar_arcWidth, 15);
        mStartAngle = typedArray.getFloat(R.styleable.CircleProgressBar_startAngle, 110);
        mSweepAngle = typedArray.getFloat(R.styleable.CircleProgressBar_sweepAngle, 360);

        mBgArcColor = typedArray.getColor(R.styleable.CircleProgressBar_bgArcColor, Color.WHITE);
        mBgArcWidth = typedArray.getDimension(R.styleable.CircleProgressBar_bgArcWidth, 15);
        mAnimTime = typedArray.getInt(R.styleable.CircleProgressBar_animTime, 1000);
        mDottedLineCount = typedArray.getInteger(R.styleable.CircleProgressBar_dottedLineCount, mDottedLineCount);
        mLineDistance = typedArray.getInteger(R.styleable.CircleProgressBar_lineDistance, mLineDistance);
        mDottedLineWidth = typedArray.getDimension(R.styleable.CircleProgressBar_dottedLineWidth, mDottedLineWidth);

        typedArray.recycle();
    }

    private void initPaint() {

        mBgArcPaint = new Paint();
        mBgArcPaint.setAntiAlias(antiAlias);
        mBgArcPaint.setColor(mBgArcColor);
        mBgArcPaint.setStyle(Paint.Style.STROKE);
        mBgArcPaint.setStrokeWidth(mBgArcWidth);
        mBgArcPaint.setStrokeCap(Paint.Cap.SQUARE);

        mBgGrayArcPaint = new Paint();
        mBgGrayArcPaint.setAntiAlias(antiAlias);
        mBgGrayArcPaint.setColor(Color.parseColor("#80F0F0F0"));
        mBgGrayArcPaint.setStyle(Paint.Style.STROKE);
        mBgGrayArcPaint.setStrokeWidth(mBgGrayWidth);
        mBgGrayArcPaint.setStrokeCap(Paint.Cap.SQUARE);

        mProgressPaint = new Paint();
        mProgressPaint.setAntiAlias(antiAlias);
        mProgressPaint.setColor(Color.parseColor("#FF7400"));
        mProgressPaint.setStyle(Paint.Style.STROKE);
        mProgressPaint.setStrokeWidth(mProgressWidth);
        mProgressPaint.setStrokeCap(Paint.Cap.SQUARE);

        mProgressShadowPaint = new Paint();
        mProgressShadowPaint.setAntiAlias(antiAlias);
        mProgressShadowPaint.setColor(Color.TRANSPARENT);
//        mProgressShadowPaint.setColor(Color.BLACK);
        mProgressShadowPaint.setStyle(Paint.Style.STROKE);
        mProgressShadowPaint.setStrokeWidth(mProgressWidth);
        mProgressShadowPaint.setStrokeCap(Paint.Cap.ROUND);

        mCirclePaint = new Paint();
        mCirclePaint.setAntiAlias(antiAlias);
        mCirclePaint.setColor(Color.WHITE);
        mCirclePaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mCirclePaint.setStrokeWidth(5);
        mCirclePaint.setStrokeCap(Paint.Cap.ROUND);


        mProgressBgPaint = new Paint();
        mProgressBgPaint.setAntiAlias(antiAlias);
        mProgressBgPaint.setColor(Color.parseColor("#FF7400"));
        mProgressBgPaint.setStyle(Paint.Style.STROKE);
        mProgressBgPaint.setStrokeWidth(mProgressBgWidth);
        mProgressBgPaint.setStrokeCap(Paint.Cap.ROUND);

        mArcPaint = new Paint();
        mArcPaint.setAntiAlias(antiAlias);
        mArcPaint.setStyle(Paint.Style.STROKE);
        mArcPaint.setStrokeWidth(mBgArcWidth);
        mArcPaint.setStrokeCap(Paint.Cap.ROUND);
        mArcPaint.setColor(Color.parseColor("#80F0F0F0"));

        drawPaint = new Paint();
        drawPaint.setAntiAlias(antiAlias);
        drawPaint.setStyle(Paint.Style.STROKE);
        drawPaint.setStrokeWidth(dipToPx(mContext, 7));
        drawPaint.setStrokeCap(Paint.Cap.SQUARE);
        drawPaint.setColor(Color.parseColor("#FFFFFF"));

    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(measureView(widthMeasureSpec, mDefaultSize),
                measureView(heightMeasureSpec, mDefaultSize));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mArcCenterX = (int) (w / 2.f);
        //求圆弧和背景圆弧的最大宽度
        float maxArcWidth = Math.max(mArcWidth, mBgArcWidth);
        //求最小值作为实际值
        int minSize = Math.min(w - getPaddingLeft() - getPaddingRight() - 2 * (int) maxArcWidth,
                h - getPaddingTop() - getPaddingBottom() - 2 * (int) maxArcWidth);
        //减去圆弧的宽度，否则会造成部分圆弧绘制在外围
        mRadius = minSize / 2;
        //获取圆的相关参数
        mCenterPoint.x = w / 2;
        mCenterPoint.y = h / 2;
        //绘制圆弧的边界
        mRectF.left = mCenterPoint.x - mRadius - maxArcWidth / 2 + leftPointRadius;
        mRectF.top = mCenterPoint.y - mRadius - maxArcWidth / 2 + leftPointRadius;
        mRectF.right = mCenterPoint.x + mRadius + maxArcWidth / 2 - leftPointRadius;
        mRectF.bottom = mCenterPoint.y + mRadius + maxArcWidth / 2 - leftPointRadius;

        // 虚线的外部半径
        mExternalDottedLineRadius = (int) (mRectF.width() / 2 - mProgressWidth / 2);
        // 虚线的内部半径
        mInsideDottedLineRadius = mExternalDottedLineRadius - mProgressWidth;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);
        drawArcBg(canvas);
        drawProgress(canvas);
        drawArc(canvas);
        //绘制四周阴影
        drawProgressShadow(canvas);
//        drawEndCircle(canvas);
//        drawProgressShadow(canvas);
    }

    private void sweepGradientCircle(int shadowColor) {
        SweepGradient sweepGradient = new SweepGradient(mArcCenterX, mArcCenterX, shadowColor, shadowColor);
        mProgressPaint.setShader(sweepGradient);
    }

    /**
     * 中间环状空气质量进度条
     *
     * @param canvas
     */
    private void drawProgress(Canvas canvas) {
        canvas.save();
        canvas.rotate(90 + (mStartAngle / 2), mCenterPoint.x, mCenterPoint.y);
        mProgressRectF.set(mRectF.left + mBgGrayWidth, mRectF.top + mBgGrayWidth, mRectF.right - mBgGrayWidth, mRectF.bottom - mBgGrayWidth);
        int color = mColorPickGradient.getColor(mPercent, end);
        mProgressPaint.setColor(color);
//        int shadowColor = mColorPickGradient.getOutShadowColorBg(end);
//        mProgressPaint.setShadowLayer(mShadowSize,0,0, shadowColor);
        canvas.drawArc(mProgressRectF, 0, (360 - mStartAngle) * mPercent, false, mProgressPaint);


        canvas.restore();
    }

    /**
     * 中间环状空气质量进度条
     *
     * @param canvas
     */
    private void drawProgressShadow(Canvas canvas) {
        canvas.save();
        canvas.rotate(90 + (mStartAngle / 2), mCenterPoint.x, mCenterPoint.y);
        mProgressRectF.set(mRectF.left + mBgGrayWidth, mRectF.top + mBgGrayWidth, mRectF.right - mBgGrayWidth, mRectF.bottom - mBgGrayWidth);
        int shadowColor = mColorPickGradient.getOutShadowColorBg(end);
//        int shadowColor = Color.parseColor("#80FE0A09");
        mProgressPaint.setColor(Color.TRANSPARENT);
        mProgressPaint.setShadowLayer(mShadowSize, 0, 0, shadowColor);
//        sweepGradientCircle(shadowColor);
        canvas.drawArc(mProgressRectF, 0, (360 - mStartAngle) * mPercent, false, mProgressPaint);


        canvas.restore();
    }

    /**
     * 绘制进度条末尾最后的圆
     *
     * @param canvas
     */
    private void drawEndCircle(Canvas canvas) {
        /*canvas.save();
        mProgressShadowPaint.setColor(Color.WHITE);
        float cx = (mRectF.left + mRectF.right) / 2.0f;
        float cy = (mRectF.top + mRectF.bottom) / 2.0f;
        float radius = (ScreenUtils.dip2px(getContext(), 10) / 2.0f);
        canvas.drawCircle(cx, cy, radius, mProgressShadowPaint);
        canvas.restore();*/
        float sweepAngle = -(145 + (360 - mStartAngle) * mPercent);
        Log.d(TAG, "->drawProgress()->sweepAngle: " + sweepAngle + ",mArcCenterX = " + mArcCenterX);
        float degrees = (float) (sweepAngle / 180 * Math.PI);
//        if(degrees > 0.001){
//            float R = mCenterPoint.x - mBgGrayWidth - mProgressWidth / 2;
        float R = mRectF.width() / 2 - mBgGrayWidth;
        float pointX = mCenterPoint.x + (float) Math.cos(degrees) * (R);
        float pointY = mCenterPoint.x - (float) Math.sin(degrees) * (R);
        float radius = (ScreenUtils.dip2px(getContext(), 9) / 2.0f);
//            Log.d(TAG, "->drawProgress()->degrees: " + sweepAngle + ",pointX = " + pointX + ";pointY = " + pointY + ";radius = " + radius);
        mCirclePaint.setColor(android.graphics.Color.parseColor("#FFFFFF"));
        canvas.drawCircle(pointX, pointY, radius, mCirclePaint);
//        }
    }

    /**
     * 绘制最外层的圆环背景
     *
     * @param canvas
     */
    private void drawArcBg(Canvas canvas) {
        canvas.save();
        canvas.rotate(90 + (mStartAngle / 2), mCenterPoint.x, mCenterPoint.y);
        mProgressRectF.set(mRectF.left + mBgGrayWidth, mRectF.top + mBgGrayWidth, mRectF.right - mBgGrayWidth, mRectF.bottom - mBgGrayWidth);
        int shadowColor = mColorPickGradient.getColorBg(end);
//        mBgGrayArcPaint.setShadowLayer(20,15,15,shadowColor);
        canvas.drawArc(mProgressRectF, 0, 360 - mStartAngle, false, mBgGrayArcPaint);
        canvas.restore();
    }

    private int start = 0;

    /**
     * 绘制刻度线
     *
     * @param canvas
     */
    private void drawArc(Canvas canvas) {
        // 绘制背景圆弧
        // 从进度圆弧结束的地方开始重新绘制，优化性能
        canvas.save();

//        canvas.rotate(90 + (mStartAngle / 2), mCenterPoint.x, mCenterPoint.y);
        for (int i = 0; i < mDottedLineCount; i++) {
            if (i == 0) {
                continue;
            }
            float sweepAngle = -(145 + (360 - mStartAngle) * (i * 1f / mDottedLineCount));
            float degrees = (float) (sweepAngle / 180 * Math.PI);

            float startX = mArcCenterX + (float) Math.cos(degrees) * mInsideDottedLineRadius;
            float startY = mArcCenterX - (float) Math.sin(degrees) * mInsideDottedLineRadius;

            float stopX = mArcCenterX + (float) Math.cos(degrees) * mExternalDottedLineRadius;
            float stopY = mArcCenterX - (float) Math.sin(degrees) * mExternalDottedLineRadius;
            if (i + 1 <= mPercent * 10) {
                drawPaint.setColor(Color.parseColor("#F0F0F0"));
            } else {
                drawPaint.setColor(Color.parseColor("#FFFFFF"));
            }
            canvas.drawLine(startX, startY, stopX, stopY, drawPaint);
        }


        // 第一个参数 oval 为 RectF 类型，即圆弧显示区域
        // startAngle 和 sweepAngle  均为 float 类型，分别表示圆弧起始角度和圆弧度数
        // 3点钟方向为0度，顺时针递增
        // 如果 startAngle < 0 或者 > 360,则相当于 startAngle % 360
        // useCenter:如果为True时，在绘制圆弧时将圆心包括在内，通常用来绘制扇形


        canvas.restore();
    }

    public boolean isAntiAlias() {
        return antiAlias;
    }

    public float getValue() {
        return mValue;
    }

    float end;

    /**
     * 设置当前值
     *
     * @param value
     */
    public void setValue(float value) {
        if (value > mMaxValue) {
            value = mMaxValue;
        }
        mValue = value;
        float start = 0;
        end = mValue / mMaxValue;
        startAnimator(start, end, mAnimTime);
        mPercent = end;
        invalidate();
    }

    private void startAnimator(float start, float end, long animTime) {
        mAnimator = ValueAnimator.ofFloat(start, end);
        mAnimator.setDuration(animTime);
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mPercent = (float) animation.getAnimatedValue();
                mValue = mPercent * mMaxValue;

                Log.d(TAG, "onAnimationUpdate: percent = " + mPercent
                        + ";currentAngle = " + (mSweepAngle * mPercent)
                        + ";value = " + mValue);

                invalidate();
            }
        });
        mAnimator.start();
    }

    /**
     * 获取最大值
     *
     * @return
     */
    public float getMaxValue() {
        return mMaxValue;
    }

    /**
     * 设置最大值
     *
     * @param maxValue
     */
    public void setMaxValue(float maxValue) {
        mMaxValue = maxValue;
    }

    public long getAnimTime() {
        return mAnimTime;
    }

    public void setAnimTime(long animTime) {
        mAnimTime = animTime;
    }

    /**
     * 重置
     */
    public void reset() {
        startAnimator(mPercent, 0.0f, 1000L);
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        //释放资源
    }

    /**
     * 测量 View
     *
     * @param measureSpec
     * @param defaultSize View 的默认大小
     * @return
     */
    private static int measureView(int measureSpec, int defaultSize) {
        int result = defaultSize;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else if (specMode == MeasureSpec.AT_MOST) {
            result = Math.min(result, specSize);
        }
        return result;
    }

    /**
     * dip 转换成px
     *
     * @param dip
     * @return
     */
    public static int dipToPx(Context context, float dip) {
        float density = context.getResources().getDisplayMetrics().density;
        return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));
    }

}
